﻿Option Explicit On
Imports System.Xml

Public Class frmEditInternalProcs

    Private saved As Boolean
    Private prevValue As Double

    Public Sub Load_InternalProcs()
        ' When the form loads, the file should be loaded and its
        ' values put into the correct text fields.  No other
        ' logic or checking takes place here.
        Try

            ' Populate the various combo boxes.
            Dim ctrl As Control

            For Each ctrl In Me.Controls
                If TypeOf ctrl Is ComboBox Then
                    With DirectCast(ctrl, ComboBox)
                        .Items.Clear()
                        .Items.Add("None")
                        .Items.Add("Str")
                        .Items.Add("AP")
                        .Items.Add("Crit")
                        .Items.Add("Haste")
                        .Items.Add("ArP")
                        .Items.Add("Agi")
                        .SelectedIndex = 0
                    End With
                End If
                If TypeOf ctrl Is TextBox Then
                    ctrl.Text = "0.000"
                End If
            Next
            ' Variables to hold the basic XML information.
            Dim m_xmld As XmlDocument
            Dim m_nodelist As XmlNodeList
            Dim m_node As XmlNode
            Dim buildinfo As FileVersionInfo = FileVersionInfo.GetVersionInfo(Windows.Forms.Application.ExecutablePath)
            Dim msgResult As DialogResult

            ' On the first run or after user deletion the data_internalprocs file will not exist in the
            ' application data directory.  Check this and copy the file if necessary to avoid
            ' writing to Program Files.  Load the correct file when the copy is complete.
            m_xmld = New XmlDocument()
            If System.IO.File.Exists(Windows.Forms.Application.CommonAppDataPath & "\data_internalprocs.xml") = False Then
                System.IO.File.Copy(Windows.Forms.Application.StartupPath & "\data_internalprocs.xml", Windows.Forms.Application.CommonAppDataPath & "\data_internalprocs.xml")
            End If

            m_xmld.Load(Windows.Forms.Application.CommonAppDataPath & "\data_internalprocs.xml")
            m_nodelist = m_xmld.SelectNodes("/internalprocs")
            m_node = m_nodelist(0)

            ' After loading the correct file, check the version.  If it is from a prior version of 
            ' DK Optimize, offer the user the option to replace the file with the more recent
            ' default values from the main appliaction directory.
            If m_node.Attributes.GetNamedItem("version").Value <> buildinfo.ProductVersion Then
                msgResult = MessageBox.Show("Internal proc data appears to be from a different version of DK Optimize.  Would you like to reload the most current default values? Existing values will be lost.", "DK Optimize", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2)
                If msgResult = Windows.Forms.DialogResult.Yes Then
                    System.IO.File.Delete(Windows.Forms.Application.CommonAppDataPath & "\data_internalprocs.xml")
                    System.IO.File.Copy(Windows.Forms.Application.StartupPath & "\data_internalprocs.xml", Windows.Forms.Application.CommonAppDataPath & "\data_internalprocs.xml")
                    m_xmld = New XmlDocument
                    m_xmld.Load(Windows.Forms.Application.CommonAppDataPath & "\data_internalprocs.xml")
                    m_nodelist = m_xmld.SelectNodes("/internalprocs")
                    m_node = m_nodelist(0)
                End If
            End If

            ' Read the values from the XML and set the text controls to the appropriate
            ' values.  When this is complete, set the saved state to true.
            txtBryntrollBlood.Text = Double.Parse(m_node.ChildNodes.Item(0).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            txtBryntrollUnholy.Text = Double.Parse(m_node.ChildNodes.Item(1).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            txtBryntrollFrost.Text = Double.Parse(m_node.ChildNodes.Item(2).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            txtBryntrollHBlood.Text = Double.Parse(m_node.ChildNodes.Item(3).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            txtBryntrollHUnholy.Text = Double.Parse(m_node.ChildNodes.Item(4).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            txtBryntrollHFrost.Text = Double.Parse(m_node.ChildNodes.Item(5).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            cboDeathbringersBlood1.SelectedIndex = Double.Parse(m_node.ChildNodes.Item(6).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            cboDeathbringersBlood2.SelectedIndex = Double.Parse(m_node.ChildNodes.Item(7).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            cboDeathbringersBlood3.SelectedIndex = Double.Parse(m_node.ChildNodes.Item(8).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            txtDeathbringersBlood.Text = Double.Parse(m_node.ChildNodes.Item(9).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            cboDeathbringersUnholy1.SelectedIndex = Double.Parse(m_node.ChildNodes.Item(10).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            cboDeathbringersUnholy2.SelectedIndex = Double.Parse(m_node.ChildNodes.Item(11).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            cboDeathbringersUnholy3.SelectedIndex = Double.Parse(m_node.ChildNodes.Item(12).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            txtDeathbringersUnholy.Text = Double.Parse(m_node.ChildNodes.Item(13).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            cboDeathbringersFrost1.SelectedIndex = Double.Parse(m_node.ChildNodes.Item(14).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            cboDeathbringersFrost2.SelectedIndex = Double.Parse(m_node.ChildNodes.Item(15).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            cboDeathbringersFrost3.SelectedIndex = Double.Parse(m_node.ChildNodes.Item(16).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            txtDeathbringersFrost.Text = Double.Parse(m_node.ChildNodes.Item(17).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            cboDeathbringersHBlood1.SelectedIndex = Double.Parse(m_node.ChildNodes.Item(18).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            cboDeathbringersHBlood2.SelectedIndex = Double.Parse(m_node.ChildNodes.Item(19).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            cboDeathbringersHBlood3.SelectedIndex = Double.Parse(m_node.ChildNodes.Item(20).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            txtDeathbringersHBlood.Text = Double.Parse(m_node.ChildNodes.Item(21).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            cboDeathbringersHUnholy1.SelectedIndex = Double.Parse(m_node.ChildNodes.Item(22).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            cboDeathbringersHUnholy2.SelectedIndex = Double.Parse(m_node.ChildNodes.Item(23).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            cboDeathbringersHUnholy3.SelectedIndex = Double.Parse(m_node.ChildNodes.Item(24).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            txtDeathbringersHUnholy.Text = Double.Parse(m_node.ChildNodes.Item(25).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            cboDeathbringersHFrost1.SelectedIndex = Double.Parse(m_node.ChildNodes.Item(26).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            cboDeathbringersHFrost2.SelectedIndex = Double.Parse(m_node.ChildNodes.Item(27).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            cboDeathbringersHFrost3.SelectedIndex = Double.Parse(m_node.ChildNodes.Item(28).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            txtDeathbringersHFrost.Text = Double.Parse(m_node.ChildNodes.Item(29).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            txtAshenBand.Text = Double.Parse(m_node.ChildNodes.Item(30).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            txtShadowmourneBuff.Text = Double.Parse(m_node.ChildNodes.Item(31).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            txtShadowmourneProcBlood.Text = Double.Parse(m_node.ChildNodes.Item(32).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            txtShadowmourneProcUnholy.Text = Double.Parse(m_node.ChildNodes.Item(33).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            txtShadowmourneProcFrost.Text = Double.Parse(m_node.ChildNodes.Item(34).InnerText, System.Globalization.CultureInfo.InvariantCulture)
            setSaved(True)
        Catch
            MessageBox.Show("There was an unspecified error while attempting to read data_internalprocs.xml. Please reinstall DK Optimize", "DK Optimize", MessageBoxButtons.OK, MessageBoxIcon.Stop, MessageBoxDefaultButton.Button1)
            End
        End Try
    End Sub

    Private Sub frmInternalProcs_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        ' When the form is closing, check to see if the weights are saved.
        ' Offer the user the ability to Yes / No / Cancel and perform
        ' the appropriate action.
        Dim msgResult As DialogResult

        If saved = False Then
            msgResult = MessageBox.Show("Internal Procs are unsaved.  Save before closing?", "DK Optimize", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1)
            If msgResult = Windows.Forms.DialogResult.Cancel Then
                e.Cancel = True
                Exit Sub
            End If
            If msgResult = Windows.Forms.DialogResult.Yes Then
                Save_InternalProcs()
            End If
        End If
    End Sub

    Private Sub setSaved(ByVal val As Boolean)
        ' Change the status of the saved variable
        ' and update the form caption to reflect
        ' whether or not the constants are saved.
        saved = val
        If saved = True Then
            Me.Text = "DK Optimize - Edit Internal Procs"
        Else
            Me.Text = "DK Optimize - Edit Internal Procs*"
        End If
    End Sub

    Private Sub btnSave_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSave.Click
        ' When the save button is clicked, save
        ' the constants by calling the Save_Constants
        ' procedure, which does the work of saving.
        Save_InternalProcs()
    End Sub

    Private Sub Save_InternalProcs()
        ' This function does the work of saving the constants
        ' back to the data_constants.xml file in the AppData location on
        ' the system.
        Try
            ' Variable declaration for the xmlWriter and version information.
            Dim xmlWriter As New XmlTextWriter(Windows.Forms.Application.CommonAppDataPath & "\data_internalprocs.xml", System.Text.Encoding.UTF8)
            Dim BuildInfo As FileVersionInfo = FileVersionInfo.GetVersionInfo(Windows.Forms.Application.ExecutablePath)

            ' Constants are written to the XML document and the saved state
            ' is set to true.
            xmlWriter.WriteStartDocument()
            xmlWriter.WriteWhitespace(vbNewLine)
            xmlWriter.WriteStartElement("internalprocs")
            xmlWriter.WriteAttributeString("version", BuildInfo.ProductVersion)
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("bryntrollblood", Double.Parse(txtBryntrollBlood.Text).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("bryntrollunholy", Double.Parse(txtBryntrollUnholy.Text).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("bryntrollfrost", Double.Parse(txtBryntrollFrost.Text).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("bryntrollhblood", Double.Parse(txtBryntrollHBlood.Text).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("bryntrollhunholy", Double.Parse(txtBryntrollHUnholy.Text).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("bryntrollhfrost", Double.Parse(txtBryntrollHFrost.Text).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringersblood1", Double.Parse(cboDeathbringersBlood1.SelectedIndex).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringersblood2", Double.Parse(cboDeathbringersBlood2.SelectedIndex).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringersblood3", Double.Parse(cboDeathbringersBlood3.SelectedIndex).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringersblooduptime", Double.Parse(txtDeathbringersBlood.Text).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringersunholy1", Double.Parse(cboDeathbringersUnholy1.SelectedIndex).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringersunholy2", Double.Parse(cboDeathbringersUnholy2.SelectedIndex).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringersunholy3", Double.Parse(cboDeathbringersUnholy3.SelectedIndex).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringersunholyuptime", Double.Parse(txtDeathbringersUnholy.Text).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringersfrost1", Double.Parse(cboDeathbringersFrost1.SelectedIndex).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringersfrost2", Double.Parse(cboDeathbringersFrost2.SelectedIndex).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringersfrost3", Double.Parse(cboDeathbringersFrost3.SelectedIndex).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringersfrostuptime", Double.Parse(txtDeathbringersFrost.Text).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringershblood1", Double.Parse(cboDeathbringersHBlood1.SelectedIndex).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringershblood2", Double.Parse(cboDeathbringersHBlood2.SelectedIndex).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringershblood3", Double.Parse(cboDeathbringersHBlood3.SelectedIndex).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringershblooduptime", Double.Parse(txtDeathbringersHBlood.Text).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringershunholy1", Double.Parse(cboDeathbringersHUnholy1.SelectedIndex).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringershunholy2", Double.Parse(cboDeathbringersHUnholy2.SelectedIndex).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringershunholy3", Double.Parse(cboDeathbringersHUnholy3.SelectedIndex).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringershunholyuptime", Double.Parse(txtDeathbringersHUnholy.Text).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringershfrost1", Double.Parse(cboDeathbringersHFrost1.SelectedIndex).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringershfrost2", Double.Parse(cboDeathbringersHFrost2.SelectedIndex).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringershfrost3", Double.Parse(cboDeathbringersHFrost3.SelectedIndex).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("deathbringershfrostuptime", Double.Parse(txtDeathbringersHFrost.Text).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("ashenbanduptime", Double.Parse(txtAshenBand.Text).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("shadowmournestr", Double.Parse(txtShadowmourneBuff.Text).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("shadowmourneblood", Double.Parse(txtShadowmourneProcBlood.Text).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("shadowmourneunholy", Double.Parse(txtShadowmourneProcUnholy.Text).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine & vbTab)
            xmlWriter.WriteElementString("shadowmournefrost", Double.Parse(txtShadowmourneProcFrost.Text).ToString(System.Globalization.CultureInfo.InvariantCulture))
            xmlWriter.WriteWhitespace(vbNewLine)
            xmlWriter.WriteEndElement()
            xmlWriter.WriteEndDocument()
            xmlWriter.Close()
            setSaved(True)
        Catch
            MessageBox.Show("An unspecified error occurred while saving.  Please reinstall DK Optimize.", "DK Optimize", MessageBoxButtons.OK, MessageBoxIcon.Stop, MessageBoxDefaultButton.Button1)
            End
        End Try

    End Sub

    Private Sub textEnter(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtBryntrollBlood.Enter, txtBryntrollUnholy.Enter, txtBryntrollFrost.Enter, txtBryntrollHBlood.Enter, txtBryntrollHUnholy.Enter, txtBryntrollHFrost.Enter, txtDeathbringersBlood.Enter, txtDeathbringersUnholy.Enter, txtDeathbringersFrost.Enter, txtDeathbringersHBlood.Enter, txtDeathbringersHUnholy.Enter, txtDeathbringersHFrost.Enter, txtAshenBand.Enter, txtShadowmourneBuff.Enter, txtShadowmourneProcBlood.Enter, txtShadowmourneProcUnholy.Enter, txtShadowmourneProcFrost.Enter
        ' When a textbox is entered, record the value before editing
        ' so it can be compared to the value when exiting to determine
        ' if the constants are still saved or not.
        prevValue = Double.Parse(DirectCast(sender, TextBox).Text)
    End Sub

    Private Sub textValidate(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtBryntrollBlood.Validating, txtBryntrollUnholy.Validating, txtBryntrollFrost.Validating, txtBryntrollHBlood.Validating, txtBryntrollHUnholy.Validating, txtBryntrollHFrost.Validating, txtDeathbringersBlood.Validating, txtDeathbringersUnholy.Validating, txtDeathbringersFrost.Validating, txtDeathbringersHBlood.Validating, txtDeathbringersHUnholy.Validating, txtDeathbringersHFrost.Validating, txtAshenBand.Validating, txtShadowmourneBuff.Validating, txtShadowmourneProcBlood.Validating, txtShadowmourneProcUnholy.Validating, txtShadowmourneProcFrost.Validating
        ' When the user leaves a text cell, perform validation to make sure that
        ' the weights contain acceptable values that make sense to the overall
        ' picture.

        ' Variables to hold the sending textbox and 
        ' a message result.
        Dim myText As TextBox
        Dim msgResult As DialogResult

        ' If the user has left the text box empty, set it to the default
        ' value.  For some this is zero, for others it is a value of one.
        myText = DirectCast(sender, TextBox)
        If myText.Text = "" Then
            myText.Text = "0"
        End If

        ' Perform checks to verify that the results are numeric, that they
        ' are between the specified bounds, and that specific weights
        ' are non-zero.  If any of these checks fail, cancel validation
        ' and set the focus to the guilty control.
        If IsNumeric(myText.Text) = False Then
            msgResult = MessageBox.Show("Invalid value.  Must be numeric.", "DK Optimize", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1)
            myText.Focus()
            Exit Sub
        End If
        If Double.Parse(myText.Text) > 10000 Or Double.Parse(myText.Text) < 0 Then
            msgResult = MessageBox.Show("Invalid value.  Must be non-negative and less than 10000.", "DK Optimize", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1)
            myText.Focus()
            Exit Sub
        End If
        ' If the value has changed since the user entered this textbox, set
        ' the status of the saved variable to false.  This will also update
        ' the form caption.
        If prevValue <> Double.Parse(myText.Text) Then
            setSaved(False)
        End If

    End Sub

    Private Sub comboChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles cboDeathbringersBlood1.SelectedIndexChanged, cboDeathbringersBlood2.SelectedIndexChanged, cboDeathbringersBlood3.SelectedIndexChanged, cboDeathbringersUnholy1.SelectedIndexChanged, cboDeathbringersUnholy2.SelectedIndexChanged, cboDeathbringersUnholy3.SelectedIndexChanged, cboDeathbringersFrost1.SelectedIndexChanged, cboDeathbringersFrost2.SelectedIndexChanged, cboDeathbringersFrost3.SelectedIndexChanged, cboDeathbringersHBlood1.SelectedIndexChanged, cboDeathbringersHBlood2.SelectedIndexChanged, cboDeathbringersHBlood3.SelectedIndexChanged, cboDeathbringersHUnholy1.SelectedIndexChanged, cboDeathbringersHUnholy2.SelectedIndexChanged, cboDeathbringersHUnholy3.SelectedIndexChanged, cboDeathbringersHFrost1.SelectedIndexChanged, cboDeathbringersHFrost2.SelectedIndexChanged, cboDeathbringersHFrost3.SelectedIndexChanged
        ' Make sure stats are not duplicated etc.
        Dim myname As String
        Dim controlsToCheck(0 To 2) As String
        Dim loopvar As Integer
        ' First goal is to figure out the three control names that are in use here.
        ' We know this from the name of the calling control.
        myname = DirectCast(sender, ComboBox).Name

        For loopvar = 0 To 2
            controlsToCheck(loopvar) = myname.Substring(0, myname.Length - 1) & loopvar + 1
        Next

        ' Now if anything is duplicated, throw an error and set the calling one to 'None'

        Dim c1, c2, c3 As ComboBox

        c1 = DirectCast(FindControl(controlsToCheck(0), Me), ComboBox)
        c2 = DirectCast(FindControl(controlsToCheck(1), Me), ComboBox)
        c3 = DirectCast(FindControl(controlsToCheck(2), Me), ComboBox)

        If (c1.SelectedIndex = c2.SelectedIndex Or c1.SelectedIndex = c3.SelectedIndex) And (c1.SelectedIndex > 0) Then
            MessageBox.Show("Invalid selection. Stats cannot be selected twice.", "DK Optimize", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1)
            DirectCast(sender, ComboBox).SelectedIndex = 0
            DirectCast(sender, ComboBox).Focus()
        End If
        If c2.SelectedIndex = c3.SelectedIndex And c2.SelectedIndex > 0 Then
            MessageBox.Show("Invalid selection. Stats cannot be selected twice.", "DK Optimize", MessageBoxButtons.OK, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button1)
            DirectCast(sender, ComboBox).SelectedIndex = 0
            DirectCast(sender, ComboBox).Focus()
        End If

        ' No longer saved
        setSaved(False)
    End Sub

    Private Function FindControl(ByVal ControlName As String, ByVal CurrentControl As Control) As Control
        For Each ctr As Control In CurrentControl.Controls
            If ctr.Name = ControlName Then
                Return ctr
            Else
                ctr = FindControl(ControlName, ctr)
                If Not ctr Is Nothing Then
                    Return ctr
                End If
            End If
        Next ctr
        ' Error here
        Return Nothing
    End Function

End Class